﻿using System;
using BusinessObjects;
using System.Collections.ObjectModel;
using System.IO;
using System.Xml.Serialization;
using YourWorld.Common.Services;
using System.Windows.Threading;
using System.Text;
using System.Collections.Generic;
using YourWorld.Common.GreenWorldEntitiesService;
using System.Data.Services.Client;
using System.Linq;
using System.Diagnostics;
using YourWorld.Common;

namespace MainGameModule.Models
{
    public class GameModel : IGameModel
    {
        private const string ServiceUrl = @"http://48de1d712dd7438f8e308ea3b1e69aae.cloudapp.net/GreenWorldDataService.svc";

        private Player playerToSubscribe;

        private int countsOfPingsToTheServer;
        private const int MaxCountsOfPingsToTheServer = 3;

        private SocketCommunicator comminicator;
        private GreenWorldEntities entities;

        private bool isServerStartRequested = false;

        public event Action<Player> SubscribeSucceeded;
        public event Action<Exception> SubscribeFailed;

        public event Action<int> PlayerUnsubscribed;

        public event Action<Game> GameInitialized;

        public event Action UnSubscribeSucceeded;
        public event Action<Exception> UnSubscribeFailed;

        public event Action<string> NotificationReceived;
        public event Action<MoveMessage> PlayerActionReceived;
        public event Action<BinsUpdateMessage> BinsUpdateMessageReceived;

        public event Action HitRubbishReceived;
        public event Action HitHerbReceived;
        public event Action ShowQuestionReceived;

        public event Action InitializeSucceeded;
        public event Action<Exception> ServerFailed;
        public event Action<ChatMessage> ChatMessageReceived;

        public event Action<List<RegionObjectHolder>> RubbishUpdateReceived;

        public event Action<PlayerConnectionMessage> PlayerConnectionRequestReceived;
        public event Action<PlayerConnectionMessage> PlayerConnectionResponseReceived;

        public event Action<Event> SupportQuestReceived;
        public event Action<Event> JoinQuestReceived;

        public event Action<EventFeedback, bool> QuestResponseReceived;
        public event Action<TeamEvent> QuestCompleted;

        public event Action<int, int, RegionObjectHolder> PublishBuildQuestReceived;
        public event Action<BadgeUpdateHolder> PublishBadgeWon;

        public event Action<Event> BuildQuestRequestReceived;
        public event Action<TeamEvent> BuildTeamQuestRequestReceived;

        public GameModel()
        {
            this.entities = new GreenWorldEntities( new Uri( ServiceUrl, UriKind.RelativeOrAbsolute ) );
        }

        public void InitializeCommunicator()
        {
            this.comminicator = new SocketCommunicator();

            this.comminicator.SocketConnected = this.PlayerConnected;
            this.comminicator.PlayerSubscribedCompleted = this.PlayerSubscribeCompleted;
            this.comminicator.GameInitializationCompleted = this.LoadMapGrid;
            this.comminicator.MoveToPositionCompleted = this.MoveToPositionCompleted;
            this.comminicator.PlayerUnsubscribedCompleted = this.PlayerUnsubscribedCompleted;
            this.comminicator.BinsUpdateCompleted = this.BinsUpdateCompleted;
            this.comminicator.RequestConnectionRetry = this.RetrySubscribeRequestReceive;
            this.comminicator.ServerCommunicationFailed = this.ErrorInServerCommunication;

            this.comminicator.SupportEventRequestReceived = this.SupportEventRequestReceived;
            this.comminicator.JoinEventRequestReceived = this.JoinEventRequestBytesReceived;

            this.comminicator.ChatMessageReceived = this.ChatMessageBytesReceived;
            this.comminicator.RubbishUpdateReceived = this.RubbishUpdateBytesReceived;

            this.comminicator.PlayerConnectionResponseReceived = this.PlayerConnectionResponseBytesReceived;
            this.comminicator.PlayerConnectionRequestReceived = this.PlayerConnectionRequestBytesReceived;

            this.comminicator.JoinEventResponseReceived = this.JoinEventResponseBytesReceived;
            this.comminicator.SupportEventResponseReceived = this.SupportEventResponseBytesReceived;
            this.comminicator.QuestCompletedEventReceived = this.QuestCompletedEventReceived;

            this.comminicator.PublishBuildQuestResponseReceived = this.PublishBuildQuestResponseReceived;
            this.comminicator.BuildQuestUpdateRequestReceived = this.RequestBuildQuestUpdate;
            this.comminicator.BuildTeamQuestUpdateRequestReceived = this.RequestBuildTeamQuestUpdate;

            this.comminicator.PublishBadgeWonReceived = this.PublishBadgeWonReceived;

            YourWorld.Common.InitializeServerManager.Instance.InitializationCompleted = this.RetrySubscribeRequestReceive;
        }

        public void DisconnectMainPlayer()
        {
            this.comminicator.Disconnect();
        }

        /// <summary>
        /// Sed the Player over the wire to the server
        /// </summary>
        /// <param name="player"></param>
        private void PlayerConnected( Player player )
        {
            XmlSerializer xmlSrl = new XmlSerializer( typeof( Player ) );
            StringWriter textWrite = new StringWriter();

            xmlSrl.Serialize( textWrite, player );
            string xml = textWrite.ToString();

            byte[] xmlMessage = Encoding.UTF8.GetBytes( xml );
            byte[] message = new byte[xmlMessage.Length + 1];

            message[0] = ( byte )SocketMessageKeys.Subscribe;
            xmlMessage.CopyTo( message, 1 );

            comminicator.SendMessage( message );
        }

        public void Subscribe( Player player )
        {
            this.playerToSubscribe = player;
            this.comminicator.Connect( player );
        }

        private void ErrorInServerCommunication( Exception e )
        {
            this.RetrySubscribeRequestReceive();
        }

        private void RetrySubscribeRequestReceive()
        {
            if ( this.playerToSubscribe != null )
                this.comminicator.Connect( this.playerToSubscribe );
        }

        private void PlayerSubscribeCompleted( byte[] message )
        {
            string xmlData = Encoding.UTF8.GetString( message, 0, message.Length );

            XmlSerializer xmlSrl = new XmlSerializer( typeof( Player ) );
            StringReader stream = new StringReader( xmlData );

            Player player = xmlSrl.Deserialize( stream ) as Player;

            if ( this.SubscribeSucceeded != null )
                this.SubscribeSucceeded( player );
        }

        private void LoadMapGrid( Game game )
        {
            int mapToSearchId = game.MapId;

            //Workaround for singleplayer
            if ( mapToSearchId != 1 ) // The Map's Id in the DB
                mapToSearchId = 1;

            var map = ( from r in this.entities.Maps where r.Id == mapToSearchId select r ) as DataServiceQuery<Map>;
            map.BeginExecute( new AsyncCallback( this.MapLoaded ), new GameInit()
            {
                MapId = game.MapId,
                MapQuery = map,
                Game = game
            } );
        }

        private void MapLoaded( IAsyncResult state )
        {
            GameInit gameInit = state.AsyncState as GameInit;
            List<Map> mapList = gameInit.MapQuery.EndExecute( state ).ToList();

            Debug.Assert( mapList.Count == 1, "Map with Id " + gameInit.MapId + " is not found! " );

            Map map = mapList[0];
            Game game = gameInit.Game;

            XmlSerializer xmlSrl = new XmlSerializer( typeof( List<string> ) );
            StringReader stream = new StringReader( map.GridDefinition );

            game.GridDefinition = xmlSrl.Deserialize( stream ) as List<string>;

            this.GameInitializationCompleted( game );
        }

        private void GameInitializationCompleted( Game game )
        {
            List<int> items;
            string[] itemsString;

            foreach ( string row in game.GridDefinition )
            {
                itemsString = row.Split( new char[] { ' ', ',' }, StringSplitOptions.RemoveEmptyEntries );
                items = new List<int>();

                foreach ( string number in itemsString )
                    items.Add( Int16.Parse( number ) );

                game.Grid.Add( items );
            }

            foreach ( RegionObjectHolder roh in game.SimplifiedGameObjects )
                game.Grid[roh.X][roh.Y] = roh.RegionObjectId;

            this.LoadRegionObjectsFromGrid( game );

            if ( this.GameInitialized != null )
                this.GameInitialized( game );
        }

        private void MoveToPositionCompleted( byte[] message )
        {
            string xmlData = Encoding.UTF8.GetString( message, 0, message.Length );
            XmlSerializer xmlSrl = new XmlSerializer( typeof( MoveMessage ) );
            StringReader stream = new StringReader( xmlData );
            MoveMessage moveMessage = null;

            try
            {
                moveMessage = xmlSrl.Deserialize( stream ) as MoveMessage;
            }
            catch
            {
            }

            if ( this.PlayerActionReceived != null && moveMessage != null )
                this.PlayerActionReceived( moveMessage );
        }

        private void PlayerUnsubscribedCompleted( byte[] message )
        {
            string xmlData = Encoding.UTF8.GetString( message, 0, message.Length );
            XmlSerializer xmlSrl = new XmlSerializer( typeof( Player ) );
            StringReader stream = new StringReader( xmlData );
            Player player = xmlSrl.Deserialize( stream ) as Player;

            if ( this.PlayerUnsubscribed != null && player != null )
                this.PlayerUnsubscribed( player.Id );
        }

        private void BinsUpdateCompleted( byte[] message )
        {
            string xmlData = Encoding.UTF8.GetString( message, 0, message.Length );
            XmlSerializer xmlSrl = new XmlSerializer( typeof( BinsUpdateMessage ) );
            StringReader stream = new StringReader( xmlData );

            BinsUpdateMessage binsUpdateMessage = xmlSrl.Deserialize( stream ) as BinsUpdateMessage;

            if ( this.BinsUpdateMessageReceived != null )
                this.BinsUpdateMessageReceived( binsUpdateMessage );
        }

        private void RubbishUpdateBytesReceived( byte[] message )
        {
            string xmlData = Encoding.UTF8.GetString( message, 0, message.Length );
            XmlSerializer xmlSrl = new XmlSerializer( typeof( List<RegionObjectHolder> ) );
            StringReader stream = new StringReader( xmlData );

            List<RegionObjectHolder> rubbishObjects = xmlSrl.Deserialize( stream ) as List<RegionObjectHolder>;

            if ( this.RubbishUpdateReceived != null )
                this.RubbishUpdateReceived( rubbishObjects );
        }

        private void QuestCompletedEventReceived( byte[] message )
        {
            string xmlData = Encoding.UTF8.GetString( message, 0, message.Length );
            XmlSerializer xmlSrl = new XmlSerializer( typeof( TeamEvent ) );
            StringReader stream = new StringReader( xmlData );

            TeamEvent quest = xmlSrl.Deserialize( stream ) as TeamEvent;

            if ( this.QuestCompleted != null )
                this.QuestCompleted( quest );
        }

        public void LoadRegionObjectsFromGrid( Game game )
        {
            game.GameObjects.Clear();

            int rowsCount = game.Grid.Count;
            int r = rowsCount;
            int c;

            List<Quest> questsToBuild = new List<Quest>();

            foreach ( List<int> row in game.Grid )
            {
                r--;
                c = 0;
                foreach ( int element in row )
                {
                    c++;
                    if ( element <= 0 || element == Consts.Unreachable )
                        continue;

                    RegionObject ro = RegionObjectsRepository.Instance.GetRegionObject( element );
                    GameObject go;

                    if ( ro.MaterialTypeId == 1 ) // Unavailable
                    {
                        go = new GameObject();
                    }
                    else
                    {   //Rubbish:
                        go = new Rubbish()
                        {
                            Type = ObjectsType.Rubbish,
                            MaterialTypeId = ro.MaterialTypeId
                        };
                    }

                    if ( ro.RequiredMembersCount > 0 )
                    {
                        BuildQuestTypes type = ( BuildQuestTypes )Enum.Parse( typeof( BuildQuestTypes ), ro.Template, true );
                        Quest quest = new Quest()
                        {
                            Width = ro.Width ?? 0,
                            Height = ro.Height ?? 0,
                            X = r * Consts.MapTileHeight,
                            Y = c * Consts.MapTileWidth,
                            QuestType = type,
                            Image = ro.Image,
                            Description = ro.Description
                        };

                        questsToBuild.Add( quest );
                        continue;
                    }

                    go.Id = ro.Id;
                    go.Image = ro.Image;
                    go.Description = ro.Description;
                    go.Y = r * Consts.MapTileHeight;
                    go.X = c * Consts.MapTileWidth;
                    go.GridX = rowsCount - 1 - r;
                    go.GridY = c - 1;
                    go.Width = ro.Width ?? Consts.MapTileWidth;
                    go.Height = ro.Height ?? Consts.MapTileHeight;

                    game.GameObjects.Add( go );
                }
            }

            foreach ( Quest quest in questsToBuild )
                this.AddQuestToMap( quest, game );
        }

        private void AddQuestToMap( Quest quest, Game game )
        {
            int gridx = game.Grid.Count - ( int )( quest.Y / Consts.MapTileWidth ) - 1;
            int gridy = ( int )( quest.X / Consts.MapTileHeight ) - 1;

            if ( gridx < 0 || gridy < 0 || game.Grid[gridx][gridy] == Consts.Unreachable )
                return;

            int xw = gridx - ( int )( quest.Height / Consts.MapTileWidth ) + 1;
            int yw = gridy + ( int )( quest.Width / Consts.MapTileHeight );

            for ( int i = xw; i < gridx; i++ )
            {
                for ( int j = gridy; j < yw; j++ )
                {
                    if ( quest.QuestType == BuildQuestTypes.WaterPlant )
                        game.Grid[i][j] = Consts.Unreachable;
                    else
                        game.Grid[i][j] = -1;
                }
            }

            game.GameObjects.Add( quest );
        }

        public void PublishMovePlayerMessage( MoveMessage moveMessage )
        {
            XmlSerializer xmlSrl = new XmlSerializer( typeof( MoveMessage ) );
            StringWriter textWrite = new StringWriter();

            xmlSrl.Serialize( textWrite, moveMessage );
            string xml = textWrite.ToString();

            byte[] xmlMessage = Encoding.UTF8.GetBytes( xml );
            byte[] message = new byte[xmlMessage.Length + 1];

            message[0] = ( byte )SocketMessageKeys.MoveToPosition;
            xmlMessage.CopyTo( message, 1 );

            comminicator.SendMessage( message );
        }

        public void UpdateSeverBinsStatus( Player player, Rubbish rubbish )
        {
            this.UpdateSeverBinsStatus( player, rubbish, RubbishRemovalStatus.UpdateServer );
        }

        public void UpdateSeverBinsStatus( Player player, Rubbish rubbish, RubbishRemovalStatus status )
        {
            BinsUpdateMessage binsMessage = new BinsUpdateMessage( player, rubbish, status );

            XmlSerializer xmlSrl = new XmlSerializer( typeof( BinsUpdateMessage ) );
            StringWriter textWrite = new StringWriter();

            xmlSrl.Serialize( textWrite, binsMessage );
            string xml = textWrite.ToString();

            byte[] xmlMessage = Encoding.UTF8.GetBytes( xml );
            byte[] message = new byte[xmlMessage.Length + 1];

            message[0] = ( byte )SocketMessageKeys.BinsStatusUpdate;
            xmlMessage.CopyTo( message, 1 );

            comminicator.SendMessage( message );
        }

        /// <summary>
        /// Send the whole player!
        /// </summary>
        /// <param name="player"></param>
        public void UnSubscribe( Player player )
        {
            XmlSerializer xmlSrl = new XmlSerializer( typeof( Player ) );
            StringWriter textWrite = new StringWriter();

            xmlSrl.Serialize( textWrite, player );
            string xml = textWrite.ToString();

            byte[] xmlMessage = Encoding.UTF8.GetBytes( xml );
            byte[] message = new byte[xmlMessage.Length + 1];

            message[0] = ( byte )SocketMessageKeys.UnSubscribe;
            xmlMessage.CopyTo( message, 1 );

            comminicator.SendMessage( message );

            if ( this.UnSubscribeSucceeded != null )
                this.UnSubscribeSucceeded();
        }

        public void Initialize( Game game )
        {
        }

        public void StartEvent( Event playerEvent )
        {
            XmlSerializer xmlSrl = new XmlSerializer( typeof( Event ) );
            StringWriter textWrite = new StringWriter();

            xmlSrl.Serialize( textWrite, playerEvent );
            string xml = textWrite.ToString();

            byte[] xmlMessage = Encoding.UTF8.GetBytes( xml );
            byte[] message = new byte[xmlMessage.Length + 1];

            message[0] = ( byte )SocketMessageKeys.StartEvent;
            xmlMessage.CopyTo( message, 1 );

            comminicator.SendMessage( message );
        }

        public void JoinEvent( EventFeedback comments )
        {
            XmlSerializer xmlSrl = new XmlSerializer( typeof( EventFeedback ) );
            StringWriter textWrite = new StringWriter();

            xmlSrl.Serialize( textWrite, comments );
            string xml = textWrite.ToString();

            byte[] xmlMessage = Encoding.UTF8.GetBytes( xml );
            byte[] message = new byte[xmlMessage.Length + 1];

            message[0] = ( byte )SocketMessageKeys.JoinEventResponse;
            xmlMessage.CopyTo( message, 1 );

            comminicator.SendMessage( message );
        }

        public void JoinEventResponseBytesReceived( byte[] message )
        {
            string xmlData = Encoding.UTF8.GetString( message, 0, message.Length );
            XmlSerializer xmlSrl = new XmlSerializer( typeof( EventFeedback ) );
            StringReader stream = new StringReader( xmlData );

            EventFeedback ef = xmlSrl.Deserialize( stream ) as EventFeedback;

            if ( this.QuestResponseReceived != null )
                this.QuestResponseReceived( ef, true );
        }

        public void SupportEventResponseBytesReceived( byte[] message )
        {
            string xmlData = Encoding.UTF8.GetString( message, 0, message.Length );
            XmlSerializer xmlSrl = new XmlSerializer( typeof( EventFeedback ) );
            StringReader stream = new StringReader( xmlData );

            EventFeedback ef = xmlSrl.Deserialize( stream ) as EventFeedback;

            if ( this.QuestResponseReceived != null )
                this.QuestResponseReceived( ef, false );
        }

        public void SupportEvent( EventFeedback comments )
        {
            XmlSerializer xmlSrl = new XmlSerializer( typeof( EventFeedback ) );
            StringWriter textWrite = new StringWriter();

            xmlSrl.Serialize( textWrite, comments );
            string xml = textWrite.ToString();

            byte[] xmlMessage = Encoding.UTF8.GetBytes( xml );
            byte[] message = new byte[xmlMessage.Length + 1];

            message[0] = ( byte )SocketMessageKeys.SupportEventResponse;
            xmlMessage.CopyTo( message, 1 );

            comminicator.SendMessage( message );
        }

        public void SupportEventRequestReceived( byte[] message )
        {
            string xmlData = Encoding.UTF8.GetString( message, 0, message.Length );
            XmlSerializer xmlSrl = new XmlSerializer( typeof( Event ) );
            StringReader stream = new StringReader( xmlData );

            Event gameEvent = xmlSrl.Deserialize( stream ) as Event;

            if ( this.SupportQuestReceived != null )
                this.SupportQuestReceived( gameEvent );
        }

        private void JoinEventRequestBytesReceived( byte[] message )
        {
            string xmlData = Encoding.UTF8.GetString( message, 0, message.Length );
            XmlSerializer xmlSrl = new XmlSerializer( typeof( Event ) );
            StringReader stream = new StringReader( xmlData );

            Event gameEvent = xmlSrl.Deserialize( stream ) as Event;

            if ( this.JoinQuestReceived != null )
                this.JoinQuestReceived( gameEvent );
        }

        private void ChatMessageBytesReceived( byte[] message )
        {
            string xmlData = Encoding.UTF8.GetString( message, 0, message.Length );
            XmlSerializer xmlSrl = new XmlSerializer( typeof( ChatMessage ) );
            StringReader stream = new StringReader( xmlData );

            ChatMessage chatMessage = xmlSrl.Deserialize( stream ) as ChatMessage;

            if ( this.ChatMessageReceived != null )
                this.ChatMessageReceived( chatMessage );
        }

        public void HelWithQuestion()
        {
            throw new NotImplementedException();
        }

        public void SendThankYouNote()
        {
            throw new NotImplementedException();
        }

        public void SendChatMessage( ChatMessage chatMessage )
        {
            XmlSerializer xmlSrl = new XmlSerializer( typeof( ChatMessage ) );
            StringWriter textWrite = new StringWriter();

            xmlSrl.Serialize( textWrite, chatMessage );
            string xml = textWrite.ToString();

            byte[] xmlMessage = Encoding.UTF8.GetBytes( xml );
            byte[] message = new byte[xmlMessage.Length + 1];

            message[0] = ( byte )SocketMessageKeys.Chat;
            xmlMessage.CopyTo( message, 1 );

            comminicator.SendMessage( message );
        }

        public void SendPlayerConnectionRequest( PlayerConnectionMessage payload )
        {
            XmlSerializer xmlSrl = new XmlSerializer( typeof( PlayerConnectionMessage ) );
            StringWriter textWrite = new StringWriter();

            xmlSrl.Serialize( textWrite, payload );
            string xml = textWrite.ToString();

            byte[] xmlMessage = Encoding.UTF8.GetBytes( xml );
            byte[] message = new byte[xmlMessage.Length + 1];

            message[0] = ( byte )SocketMessageKeys.PlayerConnectionRequest;
            xmlMessage.CopyTo( message, 1 );

            comminicator.SendMessage( message );
        }

        public void SendPlayerConnectionResponse( PlayerConnectionMessage payload )
        {
            XmlSerializer xmlSrl = new XmlSerializer( typeof( PlayerConnectionMessage ) );
            StringWriter textWrite = new StringWriter();

            xmlSrl.Serialize( textWrite, payload );
            string xml = textWrite.ToString();

            byte[] xmlMessage = Encoding.UTF8.GetBytes( xml );
            byte[] message = new byte[xmlMessage.Length + 1];

            message[0] = ( byte )SocketMessageKeys.PlayerConnectionResponse;
            xmlMessage.CopyTo( message, 1 );

            comminicator.SendMessage( message );
        }

        public void PublishBuildQuest( BuildQuestUpdateHolder update )
        {
            XmlSerializer xmlSrl = new XmlSerializer( typeof( BuildQuestUpdateHolder ) );
            StringWriter textWrite = new StringWriter();

            xmlSrl.Serialize( textWrite, update );
            string xml = textWrite.ToString();

            byte[] xmlMessage = Encoding.UTF8.GetBytes( xml );
            byte[] message = new byte[xmlMessage.Length + 1];

            message[0] = ( byte )SocketMessageKeys.BuildQuestUpdate;
            xmlMessage.CopyTo( message, 1 );

            comminicator.SendMessage( message );
        }

        public void PublishBuildQuestResponseReceived( byte[] message )
        {
            string xmlData = Encoding.UTF8.GetString( message, 0, message.Length );
            XmlSerializer xmlSrl = new XmlSerializer( typeof( BuildQuestUpdateHolder ) );
            StringReader stream = new StringReader( xmlData );

            BuildQuestUpdateHolder update = xmlSrl.Deserialize( stream ) as BuildQuestUpdateHolder;
            RegionObjectHolder roh = update.RegionObject;

            if ( this.PublishBuildQuestReceived != null )
                this.PublishBuildQuestReceived( update.QuestId, update.PlayerId, roh );
        }

        private void PlayerConnectionRequestBytesReceived( byte[] message )
        {
            string xmlData = Encoding.UTF8.GetString( message, 0, message.Length );
            XmlSerializer xmlSrl = new XmlSerializer( typeof( PlayerConnectionMessage ) );
            StringReader stream = new StringReader( xmlData );

            PlayerConnectionMessage requestMessage = xmlSrl.Deserialize( stream ) as PlayerConnectionMessage;

            if ( this.PlayerConnectionRequestReceived != null )
                this.PlayerConnectionRequestReceived( requestMessage );
        }

        private void PlayerConnectionResponseBytesReceived( byte[] message )
        {
            string xmlData = Encoding.UTF8.GetString( message, 0, message.Length );
            XmlSerializer xmlSrl = new XmlSerializer( typeof( PlayerConnectionMessage ) );
            StringReader stream = new StringReader( xmlData );

            PlayerConnectionMessage requestMessage = xmlSrl.Deserialize( stream ) as PlayerConnectionMessage;

            if ( this.PlayerConnectionResponseReceived != null )
                this.PlayerConnectionResponseReceived( requestMessage );
        }

        private void RequestBuildQuestUpdate( byte[] message )
        {
            string xmlData = Encoding.UTF8.GetString( message, 0, message.Length );
            XmlSerializer xmlSrl = new XmlSerializer( typeof( Event ) );
            StringReader stream = new StringReader( xmlData );

            Event quest = xmlSrl.Deserialize( stream ) as Event;

            if ( this.BuildQuestRequestReceived != null )
                this.BuildQuestRequestReceived( quest );
        }

        private void RequestBuildTeamQuestUpdate( byte[] message )
        {
            string xmlData = Encoding.UTF8.GetString( message, 0, message.Length );
            XmlSerializer xmlSrl = new XmlSerializer( typeof( TeamEvent ) );
            StringReader stream = new StringReader( xmlData );

            TeamEvent quest = xmlSrl.Deserialize( stream ) as TeamEvent;

            if ( this.BuildTeamQuestRequestReceived != null )
                this.BuildTeamQuestRequestReceived( quest );
        }

        public void PublishPlayerBadgeWon( BadgeUpdateHolder buh )
        {
            XmlSerializer xmlSrl = new XmlSerializer( typeof( BadgeUpdateHolder ) );
            StringWriter textWrite = new StringWriter();

            xmlSrl.Serialize( textWrite, buh );
            string xml = textWrite.ToString();

            byte[] xmlMessage = Encoding.UTF8.GetBytes( xml );
            byte[] message = new byte[xmlMessage.Length + 1];

            message[0] = ( byte )SocketMessageKeys.BadgeWonUpdate;
            xmlMessage.CopyTo( message, 1 );

            comminicator.SendMessage( message );
        }

        public void PublishBadgeWonReceived( byte[] message )
        {
            string xmlData = Encoding.UTF8.GetString( message, 0, message.Length );
            XmlSerializer xmlSrl = new XmlSerializer( typeof( BadgeUpdateHolder ) );
            StringReader stream = new StringReader( xmlData );

            BadgeUpdateHolder update = xmlSrl.Deserialize( stream ) as BadgeUpdateHolder;

            if ( this.PublishBadgeWon != null )
                this.PublishBadgeWon( update );
        }
    }

    class GameInit
    {
        public int MapId
        {
            get;
            set;
        }

        public DataServiceQuery<Map> MapQuery
        {
            get;
            set;
        }

        public Game Game
        {
            get;
            set;
        }
    }
}
